import 'package:flutter/material.dart';

/// KqSwipeItem 左滑菜单（列表）项
/// 在该物体上左滑时，会显示对应的操作按钮
///
/// @param mainWidget 物体的主体控件
/// @param actionList 操作按钮列表
/// @param actionsWidth 所有操作按钮的总宽度
class KqSwipeItem extends StatefulWidget {
  Widget mainWidget;
  List<Widget> actionList;
  double actionsWidth;
  double actionsVelocity = 200;

  KqSwipeItem(
      {super.key,
      required this.mainWidget,
      required this.actionList,
      required this.actionsWidth});

  @override
  State<StatefulWidget> createState() {
    return _KqSwipeItemState();
  }
}

class _KqSwipeItemState extends State<KqSwipeItem>
    with TickerProviderStateMixin {
  double transX = 0;
  late AnimationController animation;

  @override
  void initState() {
    super.initState();
    animation = AnimationController(
        lowerBound: -widget.actionsWidth,
        upperBound: 0,
        vsync: this,
        duration: Duration(milliseconds: 300))
      ..addListener(() {
        transX = animation.value;
        setState(() {});
      });
  }

  @override
  Widget build(BuildContext context) {
    return Stack(children: <Widget>[
      Positioned(
          right: -widget.actionsWidth,
          child: Transform.translate(
            offset: Offset(transX, 0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: widget.actionList,
            ),
          )),
      GestureDetector(
        onHorizontalDragUpdate: (v) {
          _onHorizontalSwipeUpdate(v);
        },
        onHorizontalDragEnd: (v) {
          _onHorizontalSwipeEnd(v);
        },
        child: Transform.translate(
          offset: Offset(transX, 0),
          child: Row(
            children: <Widget>[
              Expanded(
                flex: 1,
                child: widget.mainWidget,
              )
            ],
          ),
        ),
      )
    ]);
  }

  void _onHorizontalSwipeUpdate(DragUpdateDetails details) {
    transX = (transX + details.delta.dx).clamp(-widget.actionsWidth, 0);
    setState(() {});
  }

  void _onHorizontalSwipeEnd(DragEndDetails details) {
    animation.value = transX;
    if (details.velocity.pixelsPerSecond.dx > widget.actionsVelocity) {
      menuClose();
    } else if (details.velocity.pixelsPerSecond.dx < -widget.actionsVelocity) {
      menuOpen();
    } else {
      if (transX.abs() > widget.actionsWidth / 2) {
        menuOpen();
      } else {
        menuClose();
      }
    }
  }

  void menuOpen() {
    if (transX != -widget.actionsWidth) {
      animation.animateTo(-widget.actionsWidth);
    }
  }

  void menuClose() {
    if (transX != 0) {
      animation.animateTo(0);
    }
  }

  @override
  void dispose() {
    animation.dispose();
    super.dispose();
  }
}
